package com.jolink.omiis.wechat.outer;

import java.io.IOException;
import java.util.Map;

import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;

import org.junit.Assert;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import com.jolink.omiis.wechat.WeChatContext;
import com.jolink.omiis.wechat.crypt.aes.AesException;
import com.jolink.omiis.wechat.keys.IPreferences;
import com.jolink.omiis.wechat.message.AbstractMessageHandler;
import com.jolink.omiis.wechat.message.MessageHandlerFactory;
import com.jolink.omiis.wechat.message.type.UserType;

public abstract class AbstractWeChatController {
	private static Logger logger = LoggerFactory.getLogger(AbstractWeChatController.class);
	private UserType userType;

	@Autowired
	private WeChatContext context;

	/**
	 * @return the userType
	 */
	public UserType getUserType() {
		return userType;
	}

	/**
	 * @param userType
	 *            the userType to set
	 */
	public void setUserType(UserType userType) {
		this.userType = userType;
	}

	/**
	 * 读取 http-body
	 * 
	 * @param request
	 * @return
	 */
	protected String readBody(HttpServletRequest request) {
		int contentLength = request.getContentLength();
		logger.info("读取请求内容信息，ContentLength：{}，QueryString：{}。", contentLength, request.getQueryString());
		String body = null;
		if (contentLength == -1)
			return body;

		byte[] contents = new byte[contentLength];
		try {
			ServletInputStream sis = request.getInputStream();
			sis.read(contents, 0, contentLength);
			body = new String(contents);
		} catch (IOException e) {
			logger.error(e.getMessage(), e);
		} finally {
			// nothing to do
		}
		return body;
	}

	/**
	 * 此处代码是为了发布全网平台
	 * 
	 * @param reqParams
	 * @param message
	 * @return
	 */
	protected String decrypt(Map<String, String[]> reqParams, String message) {
		Map<String, String> componentInfo = context.getCompentInfo();
		logger.info("解密腾讯请求信息，三方平台信息：{}，请求参数：{}，请求信息：{}。", componentInfo, reqParams, message);
		String app_id = componentInfo.get(IPreferences.COMPONENT_APP_ID);
		String token = componentInfo.get(IPreferences.TOKEN);
		String encrypt_key = componentInfo.get(IPreferences.ENCRYPT_KEY);
		String msg_signature = reqParams.get("msg_signature")[0];
		String timestamp = reqParams.get("timestamp")[0];
		String nonce = reqParams.get("nonce")[0];
		try {
			Assert.assertNotNull("appId为空", app_id);
			Assert.assertNotNull("token为空", token);
			Assert.assertNotNull("encrypt_key为空", encrypt_key);
			Assert.assertNotNull("msg_signature为空", msg_signature);
			Assert.assertNotNull("timestamp为空", timestamp);
			Assert.assertNotNull("nonce为空", nonce);
		} catch (AssertionError e) {
			throw new RuntimeException(e.getMessage(), e.getCause());
		}
		if (message.contains(UserType.AppId.getValue())) {
			setUserType(UserType.AppId);
		} else if (message.contains(UserType.ToUserName.getValue())) {
			setUserType(UserType.ToUserName);
		} else {
			throw new RuntimeException("未知的消息类型！");
		}
		ICrypt crypt = null;
		String resultMsg = null;
		try {
			logger.info("消息发送方类型：{}，密文信息：{}，开始解密请求信息......", userType.getValue(), message);
			crypt = new Crypt(token, encrypt_key, app_id);
			resultMsg = crypt.decrypt(msg_signature, timestamp, nonce, message, getUserType());
			logger.info("解密完成，明文信息：{}", resultMsg);
		} catch (AesException e) {
			throw new RuntimeException(e.getMessage(), e);
		}
		return resultMsg;
	}

	@SuppressWarnings({ "static-access", "unchecked" })
	protected <T> T createMessageHandler(Map<String, String[]> reqParams, String message) {
		AbstractMessageHandler messageHandler = null;
		Map<String, String> componentInfo = getContext().getCompentInfo();
		logger.info("三方平台信息：{}，请求参数：{}，请求信息：{}。", componentInfo, reqParams, message);
		String app_id = componentInfo.get(IPreferences.COMPONENT_APP_ID);
		String token = componentInfo.get(IPreferences.TOKEN);
		String encrypt_key = componentInfo.get(IPreferences.ENCRYPT_KEY);
		String msg_signature = reqParams.get("msg_signature")[0];
		String timestamp = reqParams.get("timestamp")[0];
		String nonce = reqParams.get("nonce")[0];
		try {
			Assert.assertNotNull("appId为空", app_id);
			Assert.assertNotNull("token为空", token);
			Assert.assertNotNull("encrypt_key为空", encrypt_key);
			Assert.assertNotNull("msg_signature为空", msg_signature);
			Assert.assertNotNull("timestamp为空", timestamp);
			Assert.assertNotNull("nonce为空", nonce);
		} catch (AssertionError e) {
			throw new RuntimeException(e.getMessage(), e.getCause());
		}
		if (message.contains(UserType.AppId.getValue())) {
			setUserType(UserType.AppId);
		} else if (message.contains(UserType.ToUserName.getValue())) {
			setUserType(UserType.ToUserName);
		} else {
			throw new RuntimeException("未知的消息类型！");
		}
		ICrypt crypt = null;
		String resultMsg = null;
		try {
			logger.info("消息发送方类型：{}，密文信息：{}，开始解密请求信息......", userType.getValue(), message);
			crypt = new Crypt(token, encrypt_key, app_id);
			resultMsg = crypt.decrypt(msg_signature, timestamp, nonce, message, getUserType());
			logger.info("解密完成，明文信息：{}。", resultMsg);
		} catch (AesException e) {
			throw new RuntimeException(e.getMessage(), e);
		}
		messageHandler = (AbstractMessageHandler) MessageHandlerFactory.getInstance()
				.createMessageHandler(getUserType().getValue());
		messageHandler.setReqMessage(resultMsg);
		messageHandler.setReqParams(reqParams);
		return (T) messageHandler;
	}

	/**
	 * @return the context
	 */
	public WeChatContext getContext() {
		return context;
	}

	/**
	 * @param context
	 *            the context to set
	 */
	public void setContext(WeChatContext context) {
		this.context = context;
	}
}
